package com.thinkit.cms.service.site;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.thinkit.cms.api.admin.OrgService;
import com.thinkit.cms.api.site.SiteService;
import com.thinkit.cms.api.site.UserSiteSettingService;
import com.thinkit.cms.dto.admin.OrgDto;
import com.thinkit.cms.dto.content.ContentDto;
import com.thinkit.cms.dto.site.SiteDto;
import com.thinkit.cms.dto.site.UserSiteSettingDto;
import com.thinkit.cms.dto.upload.UploadDto;
import com.thinkit.cms.entity.site.Site;
import com.thinkit.cms.mapper.site.SiteMapper;
import com.thinkit.core.annotation.SiteMark;
import com.thinkit.core.base.BaseServiceImpl;
import com.thinkit.core.constant.Channel;
import com.thinkit.core.constant.Constants;
import com.thinkit.core.handler.CustomException;
import com.thinkit.nosql.annotation.CacheClear;
import com.thinkit.nosql.base.BaseRedisService;
import com.thinkit.processor.channel.ChannelThreadLocal;
import com.thinkit.utils.enums.SiteOperation;
import com.thinkit.utils.model.ApiResult;
import com.thinkit.utils.model.PageDto;
import com.thinkit.utils.model.Tree;
import com.thinkit.utils.properties.ThinkItProperties;
import com.thinkit.utils.utils.Checker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 站点管理表 服务实现类
 * </p>
 *
 * @author LG
 * @since 2020-07-22
 */
@Service
public class SiteServiceImpl extends BaseServiceImpl<SiteDto, Site, SiteMapper> implements SiteService {

    @Autowired
    ThinkItProperties thinkItProperties;

    @Autowired
    BaseRedisService baseRedisService;

    @Autowired
    UserSiteSettingService userSiteSettingService;

    @Autowired
    OrgService orgService;


    @SiteMark(type= SiteOperation.READ)
    @Override
    public PageDto<SiteDto> listPage(PageDto<SiteDto> pageDto){
        IPage<ContentDto> pages = new Page<>(pageDto.getPageNo(), pageDto.getPageSize());
        IPage<SiteDto> result = baseMapper.listPage(pages, pageDto.getDto(), getUserId(),getOrgId());
        PageDto<SiteDto> resultSearch = new PageDto(result.getTotal(), result.getPages(), result.getCurrent(), Checker.BeNotEmpty(result.getRecords()) ? result.getRecords() : Lists.newArrayList());
        return resultSearch;
    }


    @CacheClear(method = "getAllSite",key = "#clas.targetClass+'.'+#clas.method")
    @Transactional
    @Override
    public void save(SiteDto v) {
        if(ckHasDomain(v.getId(),v.getDomain())){
            throw new CustomException(ApiResult.result(5016));
        }
        ckLegal(v);
        boolean res=super.insert(v);
        mkdirDomainDire(res,v.getDomain());
    }

    @CacheClear(method = "getAllSite",keys= {"#clas.targetClass+'.'+#clas.method",
    "#clas.targetClass+'.'+getDomain+'.'+#p0.id"})
    @Transactional
    @CacheEvict(value = Constants.cacheName, key = "#root.targetClass+'.getByPk.'+#p0.id")
    @Override
    public void update(SiteDto v) {
        if(ckHasDomain(v.getId(),v.getDomain())){
            throw new CustomException(ApiResult.result(5016));
        }
        ckLegal(v);
        renameSite(v.getId(),v.getDomain());
        super.updateByPk(v);
    }

    @CacheClear(method = "getAllSite",keys = {"#clas.targetClass+'.'+#clas.method","#clas.targetClass+'.'+getDefault"} )
    @Transactional
    @Override
    public void setDefault(String siteId) {
//        baseMapper.setDefault(null);
//        baseMapper.setDefault(siteId);
//        baseRedisService.set(Constants.DEFAULT_SITE,siteId);
          userSiteSettingService.setDefaultSetting(siteId);
    }

    @Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName",unless="#result == null")
    @Override
    public String getDefault() {
//        Object siteId = baseRedisService.get(Constants.DEFAULT_SITE);
//        if(Checker.BeNull(siteId)){
//            siteId =   baseMapper.getDefault();
//            if(Checker.BeNotNull(siteId)){
//                baseRedisService.set(Constants.DEFAULT_SITE,siteId);
//            }
//        }
        String siteId = getMyDefaultSiteId();
        return Checker.BeNotNull(siteId)?siteId:null;
    }

    private String getMyDefaultSiteId(){
        List<SiteDto> siteDtos = baseMapper.getMySites(getUserId(),getOrgId());
        String siteId = null;
        if(Checker.BeNotEmpty(siteDtos)){
            for(SiteDto siteDto:siteDtos){
                if(siteDto.getIsDefault()){
                    siteId= siteDto.getId();
                    break;
                }
            }
        }
        return siteId;
    }

    @Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName+'.'+#p1",unless="#result == null")
    @Override
    public String getDomain(String schema,String siteId) {
        return baseMapper.getDomain(schema,siteId);
    }


    //@Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName+'.'+#p1",unless="#result == null")
    @Override
    public String getDomainCode(String siteId) {
        return baseMapper.domainCode(siteId);
    }

    // @Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName+'.'+#p1",unless="#result == null")
    @Override
    public Map<String, Object> getDomainCode(Boolean ssl,String siteId) {
        String urlPrefix="";
        if(Checker.BeNotNull(ssl)){
            urlPrefix ="http://";
            if(ssl){
                urlPrefix = "https://";
            }
        }
        return baseMapper.getDomainCode(urlPrefix,siteId);
    }

    @Override
    public String getDestPath(boolean containCode,String siteId) {
        return baseMapper.getDestPath(containCode,siteId);
    }

    @Override
    public Map<String,Object> findHomePageFile() {
        return baseMapper.findHomePageFile(getSiteId(true));
    }

    @Override
    @CacheEvict(value = Constants.cacheName, key = "#root.targetClass+'.getByPk.'+#root.args[0]")
    @CacheClear(method = "getAllSite",key = "#clas.targetClass+'.'+#clas.method")
    public boolean delete(String id) {
        SiteDto siteDto = getByPk(id);
        if(siteDto.getIsDefault()){
            throw new  CustomException(ApiResult.result(5021));
        }
        return super.deleteByPk(id);
    }

    //@Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName+'.'+#p1+'.'+#p2",unless="#result == null")
    @Override
    public List<SiteDto> getAllSite(SiteDto v,String userId,String orgId) {
        List<SiteDto> sites = baseMapper.getMySites(userId,orgId);
        // List<SiteDto> sites= baseMapper.getAllSite(v);
        return Checker.BeNotEmpty(sites)?sites: Lists.newArrayList();
    }

    @Override
    public Map<String, Object> direForSiteInfo() {
          Map<String, Object> map = baseMapper.direFoeSiteInfo(ChannelThreadLocal.get(Channel.SITE_ID).toString());
          if(Checker.BeNotEmpty(map) && map.containsKey("siteLogo") && map.get("siteLogo")!=null){
              String siteLogoJson = map.get("siteLogo").toString();
              UploadDto uploadDto = JSONUtil.toBean(siteLogoJson,UploadDto.class);
              if(Checker.BeNotNull(uploadDto)){
                  map.put("siteLogo",uploadDto.getUrl());
              }
          }
          return map;
    }


    @Override
    public Tree<OrgDto> getOrgTres() {
        return orgService.selectTreeList();
    }

    //TODO 设置为组织默认 屏蔽了
    @Override
    public void setOrgDefault(String siteId) {
        SiteDto siteDto = super.getByPk(siteId);
        String orgId = siteDto.getOrgId();
        List<String> userIds = null;//adminClientFegin.getUserIdsByOrgId(orgId);
        if(Checker.BeNotEmpty(userIds)){
            for(String userId:userIds){
                  List<UserSiteSettingDto> settingDtos= userSiteSettingService.getByUserId(userId);
                  if(Checker.BeEmpty(settingDtos)){
                      userSiteSettingService.saveSetting(orgId,userId,siteId);
                  }
            }
        }
    }

    private void renameSite(String id,String newSiteName){
        SiteDto siteDto = getByPk(id);
        if(Checker.BeNotNull(siteDto) && Checker.BeNotBlank(siteDto.getDomain())){
            if(!newSiteName.equals(siteDto.getDomain()) || !FileUtil.exist(siteDto.getDomain())){
                String separator =Constants.SEPARATOR;
                String root = thinkItProperties.getPath().getRootPath();
                ThinkItProperties.path.site site =  thinkItProperties.getPath().getSite();
                String siteName = root+separator+site.getPathName()+separator+siteDto.getDomain();
                if(FileUtil.exist(siteName)&&FileUtil.isDirectory(siteName)){
                    FileUtil.rename(new File(siteName),newSiteName,true);
                }else{
                    FileUtil.mkdir(siteName);
                }
            }
        }
    }

    private void ckLegal(SiteDto v){
       if(v.getDomain().contains("http://")){
           v.setDomain(v.getDomain().replace("http://",""));
       }
       if(Checker.BeNull(v.getSiteKeyWords())){
           v.setSiteKeyWords("");
       }
    }

    private boolean ckHasDomain(String id,String domain){
       return  baseMapper.ckHasDomain(id,domain) > 0;
    }

    private void mkdirDomainDire(boolean res,String domain){
        if(res){
            String separator =Constants.SEPARATOR;
            String root = thinkItProperties.getPath().getRootPath();
            if(Checker.BeBlank(root)){
                throw new CustomException(ApiResult.result(5017));
            }
            ThinkItProperties.path.source source =  thinkItProperties.getPath().getSource();
            ThinkItProperties.path.site site =  thinkItProperties.getPath().getSite();
            String domainPath= root+separator+ site.getPathName()+separator+domain;
            String temlpateRoot = root+separator+source.getPathName();
            String temlpates = Checker.BeNotBlank(source.getTemplates())?source.getTemplates():"temlpates";
            temlpates = temlpateRoot+separator+temlpates;
            mkdirDirectories(Arrays.asList(root,domainPath,temlpates));
        }
    }

    private void mkdirDirectories(List<String> directories){
        if(Checker.BeNotEmpty(directories)){
            for(String directorie:directories){
                boolean isCreate = Checker.BeNotBlank(directorie) && !FileUtil.exist(directorie);
                if(isCreate){
                    FileUtil.mkdir(directorie);
                }
            }
        }
    }
}
